home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 98
/
Skunkware 98.iso
/
src
/
interp
/
tclStruct1.2.tar.gz
/
tclStruct1.2.tar
/
tclStruct1.2
/
stTrNum.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-10-17
|
6KB
|
247 lines
/*
* tclStruct package
* Support 'C' structures in Tcl
*
* Written by Matthew Costello
* (c) 1995 AT&T Global Information Solutions, Dayton Ohio USA
*
* See the file "license.terms" for information on usage and
* redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "stInternal.h"
STRUCT_SCCSID("@(#)tclStruct:stTrNum.c 1.2 95/10/17")
int
Struct_GetBinaryInt( ptr, length, flags )
void *ptr;
int length;
int flags;
{
int v;
unsigned char *p = ptr;
if (flags & STRUCT_FLAG_BIG_ENDIAN) {
v = ( !(flags & STRUCT_FLAG_UNSIGNED) &&
(*p & (1<<(CHAR_BIT-1))) ) ? ~0 : 0;
while (--length >= 0)
v = (v << CHAR_BIT) | *p++;
} else {
p += length - 1;
v = ( !(flags & STRUCT_FLAG_UNSIGNED) &&
(*p & (1<<(CHAR_BIT-1))) ) ? ~0 : 0;
while (--length >= 0)
v = (v << CHAR_BIT) | *p--;
}
return v;
}
void
Struct_PutBinaryInt( v, ptr, length, flags )
int v;
void *ptr;
int length;
int flags;
{
unsigned char *p = ptr;
if (flags & STRUCT_FLAG_BIG_ENDIAN) {
p += length;
while (--length >= 0) {
*--p = (unsigned char) v;
v >>= CHAR_BIT;
}
} else {
while (--length >= 0) {
*p++ = (unsigned char) v;
v >>= CHAR_BIT;
}
}
}
/* I/O Int Trace */
char *
Struct_TraceInt(cdata, interp,name1,name2,flags)
ClientData cdata;
Tcl_Interp *interp;
char *name1,*name2;
int flags;
{
Struct_Object *object = (Struct_Object *)cdata;
static char res[80];
int v;
if (flags & TCL_TRACE_READS) {
/* Read an int : */
#ifdef DEBUG
if (struct_debug & (DBG_INT))
printf("Struct_TraceInt: Read integer %s\n",
Struct_ObjectName(object,0) );
#endif
v = Struct_GetBinaryInt( object->data, object->size, object->type->flags );
sprintf(res,(object->type->flags & STRUCT_FLAG_UNSIGNED) ? "%u" : "%d", v );
#ifdef DEBUG
if (struct_debug & (DBG_INT))
printf(", value = %s\n", res );
#endif
Tcl_SetVar2(interp,name1,name2,res,flags&TCL_GLOBAL_ONLY);
#ifdef DEBUG
if (struct_debug & (DBG_INT)) printf("\tv = \"%s\" (stored)\n", res );
#endif
} else if (flags & TCL_TRACE_WRITES) {
/* Write an int : */
char *s;
int v;
#ifdef DEBUG
if (struct_debug & (DBG_INT))
printf("Struct_TraceInt: Writing integer %s\n",
Struct_ObjectName(object,0) );
#endif
s = Tcl_GetVar2(interp,name1,name2,flags&TCL_GLOBAL_ONLY);
if (s == NULL)
return "null ptr in int write";
if (Tcl_GetInt(interp,s,&v)==TCL_ERROR) return "not a valid int";
if (object->type->flags & STRUCT_FLAG_STRICT) {
if (object->type->flags & STRUCT_FLAG_UNSIGNED) {
if (*s == '-')
return "number is negative";
if ( (object->size < sizeof(int)) &&
((unsigned)v >= (1 << (object->size * 8))) )
return "number too large";
} else {
if (object->size < sizeof(int)) {
if (v >= (int)(1 << (object->size * 8 - 1)))
return "number too positive";
else if (v < -(int)(1 << (object->size * 8 - 1)))
return "number too negative";
} else if (*s == '-') {
if (v > 0)
return "number too negative";
} else {
if (v < 0)
return "number too positive";
}
}
if ( !(object->type->flags & STRUCT_FLAG_NULL_OK) &&
(v == 0) )
return "number is zero";
}
/* Use memcpy to avoid bus error for misalignment */
Struct_PutBinaryInt( v, object->data, object->size, object->type->flags );
} else {
/* Unset : */
#ifdef DEBUG
printf("\tunset!\n");
#endif
Struct_DeleteObject(object);
}
return NULL;
}
/* I/O Double Trace */
char *
Struct_TraceDouble(cdata, interp,name1,name2,flags)
ClientData cdata;
Tcl_Interp *interp;
char *name1,*name2;
int flags;
{
Struct_Object *object = (Struct_Object *)cdata;
static char res[80];
double v;
if (flags & TCL_TRACE_READS) {
/* Read a double : */
memcpy(&v,object->data,sizeof(v)); /* avoid bus error for misalignment */
Tcl_PrintDouble(interp,v,res);
Tcl_SetVar2(interp,name1,name2,res,flags&TCL_GLOBAL_ONLY);
} else if (flags & TCL_TRACE_WRITES) {
/* Write a double : */
char *r;
r=Tcl_GetVar2(interp,name1,name2,flags&TCL_GLOBAL_ONLY);
if (r==NULL) return "null ptr in double write";
if (Tcl_GetDouble(interp,r,&v)==TCL_ERROR) return "not a valid double";
if (object->type->flags & STRUCT_FLAG_STRICT) {
if ( (object->type->flags & STRUCT_FLAG_UNSIGNED) &&
(v < 0.0) )
return "number is negative";
if ( !(object->type->flags & STRUCT_FLAG_NULL_OK) &&
(v == 0.0) )
return "number is zero";
}
memcpy(object->data,&v,sizeof(v)); /* avoid bus error for misalignment */
} else {
/* Unset : */
#ifdef DEBUG
printf("\tunset!\n");
#endif
Struct_DeleteObject(object);
}
return NULL;
}
/* I/O Float Trace */
char *
Struct_TraceFloat(cdata, interp,name1,name2,flags)
ClientData cdata;
Tcl_Interp *interp;
char *name1,*name2;
int flags;
{
Struct_Object *object = (Struct_Object *)cdata;
static char res[80];
float v;
double d;
if (flags & TCL_TRACE_READS) {
/* Read a float : */
memcpy(&v,object->data,sizeof(v)); /* avoid bus error for misalignment */
d=v;
Tcl_PrintDouble(interp,d,res);
#ifdef DEBUG
if (struct_debug & (DBG_FLOAT))
printf("f=%f,d=%f,r=%s,s=%d\n",v,d,res,sizeof(v));
#endif
Tcl_SetVar2(interp,name1,name2,res,flags&TCL_GLOBAL_ONLY);
} else if (flags & TCL_TRACE_WRITES) {
/* Write a float : */
char *r;
r=Tcl_GetVar2(interp,name1,name2,flags&TCL_GLOBAL_ONLY);
if (r==NULL) return "null ptr in float write";
if (Tcl_GetDouble(interp,r,&d)==TCL_ERROR) return "not a valid float";
if (object->type->flags & STRUCT_FLAG_STRICT) {
if (d > FLT_MAX)
return "number too positive";
if (object->type->flags & STRUCT_FLAG_UNSIGNED) {
if (d < 0.0)
return "number is negative";
} else {
if (d < -FLT_MAX)
return "number too negative";
}
if ( !(object->type->flags & STRUCT_FLAG_NULL_OK) &&
(d == 0.0) )
return "number is zero";
}
v=d;
#ifdef DEBUG
if (struct_debug & (DBG_FLOAT))
printf("f=%f,d=%f,r=%s,s=%d\n",v,d,r,sizeof(v));
#endif
memcpy(object->data,&v,sizeof(v)); /* avoid bus error for misalignment */
} else {
/* Unset : */
#ifdef DEBUG
printf("\tunset!\n");
#endif
Struct_DeleteObject(object);
}
return NULL;
}